package com.example.duanjunjie.learn.wk;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.functions.Func1;

/**
 * Created by duanjunjie on 2018/7/21.
 */
public class WKNoticeMessageHandlerThread extends HandlerThread implements Handler.Callback {
    private Handler mWorkHandler;
    private Handler mUIHandler;
    private WKListenerList<WKMessageListener> mListenerList;

    public final static int MSG_ADD_LISTENER = 1;
    public final static int MSG_REMOVE_LISTENER = 2;
    public final static int MSG_HANDLE_WKMESSAGE = 3;
    public final static int MSG_CONNECT_ESTABLISHED = 4;
    public final static int MSG_CONNECT_LOST = 5;

    public WKNoticeMessageHandlerThread(String name, WKListenerList listenerList) {
        super(name);
        mListenerList = listenerList;
        mUIHandler = getUIHandler();
    }

    @Override
    public void run() {
        super.run();
    }

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_ADD_LISTENER:
                if (msg.obj instanceof WKMessageListener) {
                    addListener((WKMessageListener) msg.obj);
                }
                break;
            case MSG_REMOVE_LISTENER:
                if (msg.obj instanceof WKMessageListener) {
                    removeListener((WKMessageListener) msg.obj);
                }
                break;
            case MSG_HANDLE_WKMESSAGE:
                if (msg.obj instanceof WKNoticeMessagePacket) {
                    parseAndDispatchMessage((WKNoticeMessagePacket) msg.obj);
                }
                break;
            case MSG_CONNECT_ESTABLISHED:
                onWKConnectEstablished();
                break;
            case MSG_CONNECT_LOST:
                onWKConnectLost();
                break;
        }
        return true;
    }

    private void onWKConnectLost() {
        mListenerList.invoke(new Func1<WKMessageListener, Void>() {
            @Override
            public Void call(final WKMessageListener listener) {
                mUIHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        listener.onWKConnectLost();
                    }
                });
                return null;
            }
        });
    }

    private void onWKConnectEstablished() {
        mListenerList.invoke(new Func1<WKMessageListener, Void>() {
            @Override
            public Void call(final WKMessageListener listener) {
                mUIHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        listener.onWKConnectEstablished();
                    }
                });
                return null;
            }
        });
    }

    private void parseAndDispatchMessage(WKNoticeMessagePacket packet) {
        try {
            final Observable<WKNoticeMessagePacket> packetObservable = getPacketObservable(packet);
            mListenerList.invoke(new Func1<WKMessageListener, Void>() {
                @Override
                public Void call(final WKMessageListener listener) {
                    packetObservable.filter(new Func1<WKNoticeMessagePacket, Boolean>() {
                        @Override
                        public Boolean call(WKNoticeMessagePacket packet) {
                            return listener.renderParser().canParse(packet);
                        }
                    }).map(new Func1<WKNoticeMessagePacket, WKNoticeMessageBase>() {
                        @Override
                        public WKNoticeMessageBase call(WKNoticeMessagePacket packet) {
                            WKNoticeMessageBase messageBase = new WKNoticeMessageBase();
                            messageBase.data = listener.renderParser().parse(packet);
                            messageBase.type = packet.type;
                            return messageBase;
                        }
                    }).observeOn(AndroidSchedulers.mainThread())
                            .subscribe(new Action1<WKNoticeMessageBase>() {
                                @Override
                                public void call(WKNoticeMessageBase messageBase) {
                                    if (messageBase.data != null) {
                                        listener.onReceiveWuKongMessage(messageBase);
                                    }
                                }
                            });
                    return null;
                }
            });
        } catch (Exception e) {

        }
    }

    private Observable<WKNoticeMessagePacket> getPacketObservable(final WKNoticeMessagePacket packet) {
        return Observable.create(new Observable.OnSubscribe<WKNoticeMessagePacket>() {
            @Override
            public void call(Subscriber<? super WKNoticeMessagePacket> subscriber) {
                subscriber.onNext(packet);
            }
        });
    }

    private void addListener(WKMessageListener listener) {
        try {
            mListenerList.add(listener);
        } catch (Exception e) {
        }
    }

    private void removeListener(WKMessageListener listener) {
        try {
            mListenerList.remove(listener);
        } catch (Exception e) {
        }
    }

    public Handler getWorkHandler() {
        if (mWorkHandler == null) {
            mWorkHandler = new Handler(getLooper(), this);
        }
        return mWorkHandler;
    }

    public Handler getUIHandler() {
        if (mUIHandler == null) {
            mUIHandler = new Handler(Looper.getMainLooper());
        }
        return mUIHandler;
    }

}
